package jian.testcase.definition;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

public abstract class TestCaseAbstract implements ITestCase {

	protected Map<Integer, Method> testMethodMap = new HashMap<Integer, Method>();

	public TestCaseAbstract() {
		int counter = 0;
		for (Method method : this.getClass().getDeclaredMethods()) {

			if (this.checkTestCaseMethod(method)) {
				testMethodMap.put(++counter, method);
			}
		}
	}

	@Override
	public StringBuffer listTestMethods() {
		StringBuffer sb = new StringBuffer();
		try {
			for (Integer methodNum : testMethodMap.keySet()) {
				sb.append("\t ");
				sb.append(methodNum);
				sb.append(" : ");
				sb.append(testMethodMap.get(methodNum)
						.getAnnotation(TestCaseAnnotation.class).desc());
				sb.append("\n");
			}

		} catch (Exception e) {
		}

		return sb;
	}

	@Override
	public StringBuffer listMethodParams(int methodNum) {
		// TODO 目前参数列举的实现依赖于方法注解的标识，需要手动维护
		StringBuffer sb = new StringBuffer("\t ");
		if (testMethodMap.containsKey(methodNum)) {
			sb.append(testMethodMap.get(methodNum)
					.getAnnotation(TestCaseAnnotation.class).paramsDesc());
		}
		sb.append("\n");
		return sb;
	}

	@Override
	public void testExecute(int num, String... args) {
		try {
			if (testMethodMap.containsKey(num)) {
				Method executeMethod = testMethodMap.get(num);
				StringBuffer sb = new StringBuffer("开始执行 ==> ");
				sb.append(executeMethod.getAnnotation(TestCaseAnnotation.class)
						.desc());
				sb.append("\t参数列表：[ ");
				for (String arg : args) {
					sb.append(arg);
					sb.append(", ");
				}
				sb.append("]");
				System.out.println(sb);
				executeMethod.invoke(this, (Object) args);
			}
		} catch (IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	private boolean checkTestCaseMethod(Method method) {
		return method.getName().startsWith("test")
				&& Modifier.isPublic(method.getModifiers())
				&& method.getReturnType().equals(Boolean.TYPE)
				&& method.getAnnotation(TestCaseAnnotation.class) != null
				&& !Modifier.isAbstract(method.getModifiers());

	}
}
